/*
 * 
 * Arduino Pro Mini
 * 
 * RST            9
 * SPI SS(SDA)   10
 * SPI MOSI      11
 * SPI MISO      12
 * SPI SCK       13
 * 
 * 
*/

#include <SPI.h>
#include <MFRC522.h>

//引脚定义
#define SS_PIN          10
#define RST_PIN         9

//模式定义
#define NOCARD_MODE        0
#define WAIT_NOCARD_MODE   1
#define READ_MODE          2
#define WAIT_READ_MODE     3

//#define DEBUGMODE

//MFRC522（NFC）实例
MFRC522 mfrc522(SS_PIN, RST_PIN);

// MFRC522（NFC）状态变量
MFRC522::StatusCode status; 

// NFC写入用数组变量（最多144byte）
//{模式，音量，文件夹名，文件号码}
byte write_buffer[4];

// NFC读取用数组变量（最大144byte + CRC用2byte）
byte read_buffer[146];
byte size = sizeof(read_buffer);

//程序模式
int mode = NOCARD_MODE;

//读取信息字符串
String udp_message;
// ----------------------------------------------
//
//                   SETUP
//
// ----------------------------------------------
void setup() {

  // 串行通信初始化
  Serial.begin(9600);

  // SPI串口初始化
  SPI.begin();

  // MFRC522实例初始化
  mfrc522.PCD_Init(); 
  
}

// ----------------------------------------------
//
//                   LOOP
//
// ----------------------------------------------
void loop() {
  #ifdef DEBUGMODE
    Serial.print("mode:");
    Serial.println(mode);
  #endif
  delay(500);
  switch(mode){
    case NOCARD_MODE:
      //开头文字
      Serial.println(F("请放入卡片"));
      Serial.println("");
      mode = WAIT_NOCARD_MODE;
      break;
    case WAIT_NOCARD_MODE:
      // 查询卡片是否插入
      if(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()){
        mode = READ_MODE;
      }
      break;
    case READ_MODE:
      cardMain();
      break;
    case WAIT_READ_MODE:
      status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(4, read_buffer, &size);
      #ifdef DEBUGMODE
        Serial.print("status:");
        Serial.println(status);
      #endif
      //卡片拔出
      if (status != MFRC522::STATUS_OK) {
        mode = NOCARD_MODE;
      }
      break;
    default:
      Serial.println("模式出错");
  }
}
//信息读取
int recvStr()
{
  int i = 0;
  int flag = 0;
  char cc[100];

  while (1) {
    if (Serial.available() > 0) {
      cc[i] = Serial.read();
      if (cc[i] == '$') break;
      i++;
      status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(4, read_buffer, &size);
      //卡片拔出
      if (status != MFRC522::STATUS_OK) {
        mode = NOCARD_MODE;
        flag = 1;
        break;
      }
    }
  }
  cc[i] = '\0';
  udp_message =cc;
  return flag;
}
//读取信息分解
int split(String data, char delimiter, String *dst) {
  int index = 0;
  int arraySize = (sizeof(data) / sizeof((data)[0]));
  int datalength = data.length();
  for (int i = 0; i < datalength; i++) {
    char tmp = data.charAt(i);
    if ( tmp == delimiter ) {
      index++;
      if ( index > (arraySize - 1)) return -1;
    }
    else dst[index] += tmp;
  }
  return (index + 1);
}
//卡片写入和确认
void cardMain(){
  // 写入信息读取
  String kari[8];
  Serial.println(F("发送写入信息:"));
  Serial.println(F("模式(0~3)"));
  Serial.println(F("音量(0~30)"));
  Serial.println(F("文件夹编号(1~100)"));
  Serial.println(F("文件名编号(1~255)"));
  Serial.println(F("文件夹内文件数(1~255)"));
  Serial.println("");

  if(recvStr() == 1){
    return;
  }
  split(udp_message,',',kari);
  for (int i =0;i<5;i++){
    write_buffer[i] = kari[i].toInt();
  }
  // 卡片写入
  status = (MFRC522::StatusCode)mfrc522.MIFARE_Ultralight_Write(4, &write_buffer[0], 4);
  status = (MFRC522::StatusCode)mfrc522.MIFARE_Ultralight_Write(5, &write_buffer[4], 4);

  // 状态确认
  if (status != MFRC522::STATUS_OK) {
    Serial.println(F("写入失败，请重新操作"));
    return;
  }
  Serial.println(F("写入成功！"));
  Serial.println();
  // 卡片读取
  Serial.println(F("卡片确认中... "));
  Serial.println("");
  status = (MFRC522::StatusCode)mfrc522.MIFARE_Read(4, read_buffer, &size);
  // 状态确认
  if (status != MFRC522::STATUS_OK) {
    Serial.println(F("读取失败，请重新操作"));
    return;
  }

  // 读取内容显示
  Serial.println(F("确认信息:"));
  
  Serial.print(F("模式:"));
  Serial.println(String(read_buffer[0],DEC));
  Serial.print(F("音量:"));
  Serial.println(String(read_buffer[1],DEC));
  Serial.print(F("文件夹号码:"));
  Serial.println(String(read_buffer[2],DEC));
  Serial.print(F("文件号码:"));
  Serial.println(String(read_buffer[3],DEC));
  Serial.print(F("文件夹内文件数:"));
  Serial.println(String(read_buffer[4],DEC));

  mode = WAIT_READ_MODE;
  Serial.println("");
  Serial.println(F("请拔出卡片"));
  Serial.println("");
}